using System;
using System.Collections;
using UnityEngine;

public class PoolBall : MonoBehaviour
{
	[Flags]
	public enum State
	{
		NONE = 0x0,
		ROLL = 0x1,
		IDLE = 0x2,
		POTTED = 0x4,
		HIDE = 0x8
	}

	public Delegate0Args onReset;

	public bool yConstrain = true;

	[SerializeField]
	protected int m_BallID = -1;

	public BallType ballType;

	public Vector3 ballTorque;

	protected Rigidbody m_Rigidbody;

	protected Vector3 m_initalPos;

	protected Quaternion m_initalRot;

	public SphereCollider sphereCollider;

	public bool AudioEnable = true;

	[SerializeField]
	protected State m_state;

	protected float m_slowTime;

	public float slowTime = 0.2f;

	public bool hitWall;

	protected BallShadowRenderer m_ShadowRenderer;

	protected Follower m_LightRenderer;

	protected Follower m_SilhouetteRenderer;

	protected PhysicalSupportTools m_BallPhysicalDrag;

	protected PhysicalSupportTools m_AngularVelocityCorrection;

	protected PhysicMaterial m_PhysicMaterial;

	[SerializeField]
	private float m_MaxYAxis;

	protected Renderer m_Mesh;

	protected Vector3 m_PrevRoundPosition;

	protected Quaternion m_PrevRoundRotation;

	protected float m_Radius;

	protected Transform _cacheTrans;

	public State BallState => m_state;

	public Follower LightRenderer => m_LightRenderer;

	public Follower silhouetteRenderer => m_SilhouetteRenderer;

	public Vector3 position => _cacheTrans.position;

	public virtual void Awake()
	{
		_cacheTrans = base.transform;
		m_Rigidbody = base.gameObject.GetComponent<Rigidbody>();
		m_Rigidbody.mass = GameConfig.BALL_MASS;
		m_ShadowRenderer = GetComponent<BallShadowRenderer>();
		m_LightRenderer = base.transform.Find("RefLight").GetComponent<Follower>();
		m_SilhouetteRenderer = base.transform.Find("Silhouette").GetComponent<Follower>();
		sphereCollider = base.gameObject.GetComponent<SphereCollider>();
		m_Mesh = GetComponent<MeshRenderer>();
		float radius = sphereCollider.radius;
		Vector3 localScale = base.transform.localScale;
		m_Radius = radius * localScale.x;
		m_BallPhysicalDrag = PhysicalSupportTools.PhysicalDragTo(base.gameObject, GameConfig.VELOCITY_DRAG, GameConfig.ANGULAR_VELOCITY_DRAG);
		m_PhysicMaterial = GetComponent<Collider>().sharedMaterial;
		CloseDrag();
	}

	public virtual void Start()
	{
		m_initalPos = base.transform.position;
		m_initalRot = base.transform.rotation;
		m_Rigidbody.useConeFriction = true;
	}

	private IEnumerator RecordYValue()
	{
		yield return new WaitForSeconds(1f);
		Vector3 position = m_Rigidbody.position;
		m_MaxYAxis = position.y;
		yield return null;
	}

	private void YValueDrag()
	{
		Vector3 position = m_Rigidbody.position;
		position.y = m_MaxYAxis;
		m_Rigidbody.position = position;
	}

	public void PointAtTarget(Vector3 target)
	{
		float magnitude = m_Rigidbody.velocity.magnitude;
		Vector3 vector = target - base.transform.position;
		m_Rigidbody.velocity = vector.normalized * magnitude;
	}

	public int GetBallID()
	{
		return m_BallID;
	}

	public void SetBallID(int id)
	{
		m_BallID = id;
	}

	public virtual void OnCollisionEnter(Collision col)
	{
		if (col.gameObject.name.Contains("Rail"))
		{
			AudioManager.BallhitRail(m_Rigidbody.velocity);
			if (!hitWall)
			{
				GameManager.Rules.BallHitRail(this);
				hitWall = true;
			}
		}
		if (col.gameObject.CompareTag("Ball") && ((m_state & (State.POTTED | State.HIDE)) == State.NONE || (col.gameObject.GetComponent<PoolBall>().BallState & (State.POTTED | State.HIDE)) == State.NONE))
		{
			AudioManager.BallhitBall(m_Rigidbody.velocity);
		}
	}

	public void OnEnable()
	{
		PoolRulesBase.onFireBall = (Delegate0Args)Delegate.Combine(PoolRulesBase.onFireBall, new Delegate0Args(OnFireBall));
		PoolRulesBase.onNewTurn = (Delegate1Args<int>)Delegate.Combine(PoolRulesBase.onNewTurn, new Delegate1Args<int>(OnNewTurn));
		OpenRenderer();
	}

	public void OnDisable()
	{
		PoolRulesBase.onFireBall = (Delegate0Args)Delegate.Remove(PoolRulesBase.onFireBall, new Delegate0Args(OnFireBall));
		PoolRulesBase.onNewTurn = (Delegate1Args<int>)Delegate.Remove(PoolRulesBase.onNewTurn, new Delegate1Args<int>(OnNewTurn));
	}

	public void OnFireBall()
	{
		m_slowTime = 0f;
	}

	public virtual void OnNewTurn(int turnIndex)
	{
		hitWall = false;
		m_PrevRoundPosition = base.transform.position;
		m_PrevRoundPosition.y = m_MaxYAxis;
		m_PrevRoundRotation = base.transform.rotation;
	}

	public float GetRadius()
	{
		return m_Radius;
	}

	public virtual void Update()
	{
		if (GameManager.Rules.State != GlobalState.GAMEOVER && !IsBallDisable())
		{
			if (m_Rigidbody.velocity.sqrMagnitude < 0.001f && m_Rigidbody.angularVelocity.sqrMagnitude < 0.001f)
			{
				m_state = State.IDLE;
				return;
			}
			m_state = State.ROLL;
			m_slowTime = 0f;
		}
	}

	private void LateUpdate()
	{
		Vector3 position = m_Rigidbody.position;
		if (position.y > m_MaxYAxis && yConstrain)
		{
			YValueDrag();
		}
	}

	public virtual void Potted(PocketIndexes pocketIndex)
	{
		if ((bool)m_Rigidbody)
		{
			m_state = State.POTTED;
			m_Rigidbody.velocity = Vector3.zero;
			m_Rigidbody.angularVelocity = Vector3.zero;
			CloseRenderer();
			base.enabled = false;
			RemovePhysicalMaterial();
			GameStatistics.MarkPottedBalls(1);
		}
	}

	protected void ResetState(Vector3 position, Quaternion rotation)
	{
		m_slowTime = 0f;
		m_state = State.IDLE;
		Vector3 position2 = base.transform.position;
		m_Rigidbody.isKinematic = false;
		position2.y = m_MaxYAxis;
		base.transform.position = position;
		base.transform.rotation = rotation;
		m_Rigidbody.constraints = RigidbodyConstraints.None;
		m_Rigidbody.angularVelocity = Vector3.zero;
		m_Rigidbody.velocity = Vector3.zero;
		m_Rigidbody.useGravity = true;
		GetComponent<Renderer>().enabled = true;
		GetComponent<Collider>().enabled = true;
		LightRenderer.Open();
		OpenRenderer();
		ReversePhysicalMaterial();
		PhysicalSupportTools.Remove(base.gameObject, PhysicalSupportType.MaxSpeedLimit);
		RackBallCollision component;
		if ((bool)(component = GetComponent<RackBallCollision>()))
		{
			UnityEngine.Object.Destroy(component);
		}
		base.enabled = true;
	}

	public virtual void Reset()
	{
		if (m_state != State.HIDE)
		{
			m_slowTime = 0f;
			m_state = State.IDLE;
			Vector3 position = base.transform.position;
			m_Rigidbody.isKinematic = false;
			position.y = m_MaxYAxis;
			ResetState(position, m_initalRot);
		}
	}

	public void BackToPrevRoundState()
	{
		ResetState(m_PrevRoundPosition, m_PrevRoundRotation);
		Pools.PutBallToThePoint(this, ref m_PrevRoundPosition);
	}

	public bool IsDoneRolling()
	{
		return m_state != State.ROLL;
	}

	public virtual void CloseRenderer()
	{
		if ((bool)m_ShadowRenderer)
		{
			m_ShadowRenderer.Close();
		}
	}

	public virtual void OpenRenderer()
	{
		if ((bool)m_ShadowRenderer)
		{
			m_ShadowRenderer.Open();
		}
	}

	public void CloseDrag()
	{
	}

	public void OpenDrag()
	{
		m_BallPhysicalDrag.enabled = true;
	}

	public void RemovePhysicalMaterial()
	{
		GetComponent<Collider>().sharedMaterial = null;
	}

	public void ReversePhysicalMaterial()
	{
		GetComponent<Collider>().sharedMaterial = m_PhysicMaterial;
	}

	[ContextMenu("Hide")]
	public void Hide()
	{
		GetComponent<Renderer>().enabled = false;
		GetComponent<Collider>().enabled = false;
		GetComponent<Rigidbody>().isKinematic = true;
		base.enabled = false;
		base.transform.Find("Shadow").gameObject.SetActive(value: false);
		GetComponent<BallShadowRenderer>().enabled = false;
		base.transform.Find("RefLight").gameObject.SetActive(value: false);
		base.transform.Find("Focus").gameObject.SetActive(value: false);
		m_state = State.HIDE;
	}

	[ContextMenu("Show")]
	public void Display()
	{
		GetComponent<Renderer>().enabled = true;
		GetComponent<Collider>().enabled = true;
		GetComponent<Rigidbody>().isKinematic = false;
		base.enabled = true;
		base.transform.Find("Shadow").gameObject.SetActive(value: true);
		GetComponent<BallShadowRenderer>().enabled = true;
		m_state = State.IDLE;
		base.transform.Find("RefLight").gameObject.SetActive(value: true);
		base.transform.Find("Focus").gameObject.SetActive(value: true);
	}

	public bool IsBallDisable()
	{
		return (m_state & (State.POTTED | State.HIDE)) != State.NONE;
	}
}
